package cloud.keveri.gateway.plugin.global;

import cloud.keveri.gateway.dto.IDefinitionDynamicManager;
import cloud.keveri.gateway.dto.Rule;
import cloud.keveri.gateway.dto.ServiceDefinition;
import cloud.keveri.gateway.dto.invoker.ServiceInvoker;
import cloud.keveri.gateway.plugin.api.context.GatewayContext;
import cloud.keveri.gateway.plugin.api.context.GatewayContextBuilder;
import cn.hutool.core.util.StrUtil;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;

import java.util.Objects;
import java.util.Optional;

import static cloud.keveri.gateway.plugin.api.GatewayPluginErrorCodeConstants.*;
import static cloud.keveri.gateway.plugin.base.ErrorHandler.handlerError;
import static cloud.keveri.gateway.plugin.base.def.Const.UNIQUE_ID;

/**
 * <p>
 * 作者：沈自在
 **/
public class DefaultGatewayContextBuilder implements GatewayContextBuilder {
    /**
     *
     */
    private final IDefinitionDynamicManager definitionDynamicManager;

    public DefaultGatewayContextBuilder(IDefinitionDynamicManager definitionDynamicManager) {
        this.definitionDynamicManager = definitionDynamicManager;
    }

    @Override
    public GatewayContext build(ServerWebExchange exchange) {
        // 1. 提取数据
        ServerHttpRequest request = exchange.getRequest();
        final String path = request.getURI().getPath();
        final String uniqueId = request.getHeaders().getFirst(UNIQUE_ID);
        if (StrUtil.isBlank(uniqueId)) {
            handlerError(exchange, UNIQUE_ID_MUST_NOT_NULL);
            return null;
        }

        // 2. 获取定义
        ServiceDefinition serviceDefinition = definitionDynamicManager.acquireServiceDefinition(uniqueId);
        if (Objects.isNull(serviceDefinition)) {
            // 2.1 兜底
            serviceDefinition = definitionDynamicManager.acquireServiceDefinitionWithPath(path);
            if (Objects.isNull(serviceDefinition)){
                handlerError(exchange, UNIQUE_INVALID);
                return null;
            }
        }

        // 3. 获取规则
        Optional<Rule> optRule = acquireRule(path, serviceDefinition.getServiceId());

        // 4. 提取 Invoker
        String invokerPath = path.replace(serviceDefinition.getPatternPath(), "");
        ServiceInvoker serviceInvoker = serviceDefinition.getInvokerMap().get(invokerPath);
        if (optRule.isEmpty() || Objects.isNull(serviceInvoker)) {
            handlerError(exchange, PATH_NO_MATCHED);
            return null;
        }
        // 5. 组装
        return GatewayContext.builder()
                .rule(optRule.get())
                .protocol(serviceDefinition.getProtocol())
                .currentRetryTimes(0)
                .invoker(serviceInvoker)
                .build();
    }

    private Optional<Rule> acquireRule(final String path, final String serviceId) {
        // 1. 处理数据
        String key = serviceId + "." + path;

        // 2. 获取 rule
        Rule rule = definitionDynamicManager.acquireRuleWithPath(key);
        if (Objects.nonNull(rule)) return Optional.of(rule);

        // 3. 兜底获取
        return definitionDynamicManager.acquireRulesWithServiceId(serviceId)
                .stream()
                .filter(r -> path.startsWith(r.getPrefix()))
                .findAny();
    }
}
